<template>
  <div
    ref="videoBox"
    class="video-player fit"
    @mouseover="onMouseOver"
    @mouseout="onMouseOut"
  >
    <video
      id="videoPlayer"
      ref="videoEl"
      class="video-js fit"
      crossorigin="anonymous"
    ></video>
    <div
      ref="videoOverlay"
      class="player-overlay fit column justify-between"
      v-show="showOverlay"
      @click="onOverlayClick"
      v-if="currentVideo && enableOverlay"
    >
      <div class="upper column q-pa-md" v-if="isFullScreen || isMaximised">
        <div class="title">{{ currentVideo.title }}</div>
        <div class="text-sub">
          {{ currentVideo.viewCount }} {{ $t('video.left.views') }} ·
          {{ currentVideo.createTimeLabel }}
        </div>
        <div class="author-info row q-my-md">
          <q-avatar size="34px">
            <img :src="currentVideo?.creatorAvatar" />
          </q-avatar>
          <div class="column q-ml-sm">
            <div class="author-name">{{ currentVideo?.creatorName }}</div>
            <div class="author-followers text-sub">
              {{ currentVideo?.creatorFollowersCount }}
              {{ $t('video.left.followers') }}
            </div>
          </div>
        </div>
      </div>
      <div class="upper" v-else />
      <div class="middle row justify-center items-center">
        <q-btn
          size="24px"
          icon="mdi-rewind-10"
          color="sub"
          flat
          @click="backward"
        />
        <q-btn
          size="36px"
          :icon="isPlaying ? 'mdi-pause' : 'mdi-play'"
          color="sub"
          flat
          @click="togglePlay"
          class="q-mx-lg"
        />
        <q-btn
          size="24px"
          icon="mdi-fast-forward-10"
          color="sub"
          flat
          @click="forward"
        />
      </div>
      <div class="lower column q-pa-md">
        <q-slider
          dense
          v-model="progress"
          :min="0"
          :max="1"
          :step="0.01"
          color="white"
          thumb-size="3px"
        />
        <div class="row justify-end items-center">
          <q-btn icon="mdi-square" dense flat @click="toggleMaximise" />
          <q-btn icon="mdi-fullscreen" dense flat @click="toggleFullscreen" />
        </div>
      </div>
    </div>
  </div>
  <audio
    class="audio-player"
    id="audioPlayer"
    ref="audioEl"
    crossorigin="anonymous"
    @loadeddata="onAudioReady"
  ></audio>
  <audio
    class="audio-player"
    id="originalAudio"
    v-if="originalAudio"
    ref="originalAudioEl"
    crossorigin="anonymous"
  ></audio>
</template>
<script lang="ts">
/* eslint-disable @typescript-eslint/no-var-requires */
import {
  defineComponent,
  ref,
  watch,
  computed,
  onMounted,
  onBeforeUnmount,
} from 'vue';
import { useQuasar } from 'quasar';
import { useRoute } from 'vue-router';
import videojs, { VideoJsPlayerOptions, VideoJsPlayer } from 'video.js';
import { useVideoStore } from 'src/stores/video-store';
import { useStudioStore } from 'stores/studio-store';
import { storeToRefs } from 'pinia';
import 'video.js/dist/video-js.css';
import gsap from 'gsap';

export default defineComponent({
  emits: [
    'inited',
    'play',
    'pause',
    'update',
    'loaded',
    'vol-change',
    'audioReady',
    'clicked',
    'maxmized',
    'minimized',
  ],
  setup(props, { emit }) {
    let hasVideo = false;
    let hasAudio = false;
    const currentRoute = useRoute();
    const enableOverlay = ref(true);
    const videoBox = ref<HTMLDivElement>();
    const isPlaying = ref(false);
    const videoStore = useVideoStore();
    const studioStore = useStudioStore();
    const { currentTime, duration, currentVideo, currentAudio, originalAudio } =
      storeToRefs(videoStore);
    const $q = useQuasar();
    const videoOverlay = ref<HTMLDivElement>();
    const videoEl = ref<HTMLVideoElement | null>(null);
    const audioEl = ref<HTMLAudioElement | null>(null);
    const originalAudioEl = ref<HTMLAudioElement | null>(null);
    const showOverlay = ref(false);
    const progress = computed<number>({
      get() {
        return currentTime.value / duration.value;
      },
      set(value) {
        videoStore.seekTo(value * duration.value);
      },
    });
    const isFullScreen = ref(false);
    const isMaximised = ref(false);
    let videoPlayer: VideoJsPlayer | null = null;
    const options: VideoJsPlayerOptions = {
      autoplay: false,
      controls: false,
      controlBar: {
        volumePanel: false,
        pictureInPictureToggle: false,
      },
    };
    const videoVolume = computed(() => videoStore.videoVolume);
    watch(videoVolume, () => {
      if (audioEl.value) {
        audioEl.value.volume = videoVolume.value;
      }
    });
    watch(currentAudio, () => {
      if (audioEl.value) {
        if (audioEl.value.src != currentAudio!.value!.url) {
          audioEl.value.src = currentAudio!.value!.url;
          audioEl.value.currentTime = videoPlayer!.currentTime();
          if (isPlaying.value) {
            audioEl.value.play();
          } else {
            // videoPlayer?.play();
          }
          hasAudio = true;
        }
      } else {
        console.log(audioEl.value);
        console.log('audioEl is not ready');
      }
    });
    watch(currentVideo, () => {
      if (videoPlayer) {
        if (!hasVideo) {
          videoPlayer.src({
            src: currentVideo!.value!.url,
          });
          hasVideo = true;
        }
      }
    });
    // function update () {
    //   if (isPlaying) {
    //     store.commit('VideoStore/setCurrnetTime', videoPlayer!.currentTime());
    //     emit('update', videoPlayer!.currentTime());
    //   }
    //   window.requestAnimationFrame(update);
    // }
    const overlayAnimationTimeline = gsap.timeline();

    onMounted(() => {
      if (currentRoute.name === 'Studio') {
        enableOverlay.value = false;
      }
      if (audioEl.value) {
        if (currentAudio && currentAudio.value) {
          if (!hasAudio) {
            console.log('videoplayer mounted method has audio infomation');
            audioEl.value.src = currentAudio.value.url;
            hasAudio = true;
          }
        } else {
          console.log(
            'videoplayer mounted method has NO audio infomation',
            audioEl.value
          );
        }
      } else {
        console.log('videoplayer mounted method got no audioEl');
      }
      if (videoEl.value) {
        videoPlayer = videojs(videoEl.value, options);
        if (currentVideo && currentVideo.value) {
          if (!hasVideo) {
            videoPlayer.src({
              src: currentVideo.value.url,
            });
            hasVideo = true;
          }
        }

        videoPlayer.on('pause', () => {
          if (currentAudio!.value && audioEl.value) {
            audioEl.value.pause();
          }
          videoStore.updateVideoState(false);
          emit('pause');
          isPlaying.value = false;
        });
        videoPlayer.on('playing', () => {
          videoStore.updateVideoState(true);
          videoPlayer?.volume(0);
          if (currentAudio!.value && audioEl.value) {
            audioEl.value.play();
          }
          emit('play');
          isPlaying.value = true;
        });
        // videoPlayer.on('volumechange', () => {
        //   store.commit('VideoStore/updateVideoVolume', videoEl.value!.volume);
        //   if (audio.value) {
        //     audioEl.value!.volume = videoEl.value!.volume;
        //   }
        //   emit('vol-change', videoEl.value!.volume);
        // });
        videoPlayer.on('timeupdate', () => {
          if (currentAudio!.value && audioEl.value) {
            // check if audio not synchronised with video
            if (
              Math.abs(videoPlayer!.currentTime() - audioEl.value.currentTime) >
              200
            ) {
              audioEl.value.currentTime = videoPlayer!.currentTime();
            }
          }
          videoStore.setCurrnetTime(videoPlayer!.currentTime());
          emit('update', videoPlayer!.currentTime());
          // progress.value = videoPlayer!.currentTime() / videoPlayer!.duration();
        });
        videoPlayer.on('seeked', () => {
          if (currentAudio!.value && audioEl.value) {
            audioEl.value.currentTime = videoPlayer!.currentTime();
          }
        });
        videoPlayer.on('loadeddata', () => {
          console.log(`Video Data Loaded: ${videoPlayer!.duration()}`);
          videoStore.setDuration(videoPlayer!.duration());
          emit('loaded', videoPlayer!.duration());
        });
        videoPlayer.on('click', () => {
          emit('clicked', 'clicked');
        });
        videoPlayer.on('ended', () => {
          videoStore.updateVideoState(false);
          emit('pause');
          isPlaying.value = false;
        });
        // videoPlayer.on('fullscreenchange', () => {
        //   if (videoPlayer!.isFullscreen()) {
        //     isFullScreen.value = true;
        //     videoPlayer!.controls(true);
        //   } else {
        //     isFullScreen.value = false;
        //     videoPlayer!.controls(false);
        //   }
        // });
        videoStore.updateVideoInstance(videoPlayer);
        videoStore.updateVideoElement(videoEl.value);
        emit('inited', videoPlayer);
        window.addEventListener('keyup', onkeyup);
        // update();
      } else {
        $q.dialog({
          title: 'Error',
          message: 'Failed to init VideoPlayer',
        });
      }
    });
    watch(videoOverlay, () => {
      if (videoOverlay.value) {
        overlayAnimationTimeline.fromTo(
          videoOverlay.value as HTMLElement,
          { opacity: 0 },
          { opacity: 1, duration: 0.5 }
        );
        overlayAnimationTimeline.to(
          videoOverlay.value as HTMLElement,
          {
            opacity: 0,
            duration: 0.5,
          },
          3
        );
      }
    });
    onBeforeUnmount(() => {
      if (videoPlayer) {
        videoPlayer.dispose();
      }
      window.removeEventListener('keyup', onkeyup);
      videoStore.currentTime = 0;
      videoStore.duration = 0;
      videoStore.isPlaying = false;
      videoStore.videoInstance = null;
      videoStore.videoElement = null;
    });
    function onkeyup(e: KeyboardEvent) {
      if (currentRoute.name === 'Studio') {
        if (studioStore.isTyping) {
          return;
        }
      }
      if (e.code === 'Space') {
        if (isPlaying.value) {
          videoPlayer?.pause();
        } else {
          videoPlayer?.play();
        }
      }
      if (e.code === 'KeyF') {
        toggleFullscreen();
      }
      if (e.code === 'ArrowLeft') {
        videoPlayer?.currentTime(videoPlayer!.currentTime() - 5);
      }
      if (e.code === 'ArrowRight') {
        videoPlayer?.currentTime(videoPlayer!.currentTime() + 5);
      }
    }
    function toggleFullscreen(evt?: Event) {
      if (evt) {
        evt.preventDefault();
        evt.stopPropagation();
      }
      if (isFullScreen.value) {
        document.exitFullscreen();
        isFullScreen.value = false;
      } else {
        videoBox.value?.requestFullscreen();
        isFullScreen.value = true;
      }
    }
    function toggleMaximise(evt?: Event) {
      if (evt) {
        evt.preventDefault();
        evt.stopPropagation();
      }
      if (isMaximised.value) {
        isMaximised.value = false;
        emit('minimized');
      } else {
        isMaximised.value = true;
        emit('maxmized');
      }
    }

    return {
      videoBox,
      enableOverlay,
      videoOverlay,
      currentVideo,
      progress,
      isPlaying,
      currentAudio,
      originalAudio,
      showOverlay,
      videoEl,
      audioEl,
      originalAudioEl,
      isFullScreen,
      isMaximised,
      toggleMaximise,
      toggleFullscreen,
      onAudioReady(event: Event) {
        emit('audioReady', audioEl.value, event);
      },
      onMouseOver(event: Event) {
        showOverlay.value = true;
        overlayAnimationTimeline.restart();
      },
      onMouseOut(event: Event) {
        showOverlay.value = false;
      },
      onMouseMove(event: Event) {
        // showOverlay.value = true;
        // if (mouseEntered.value) overlayAnimationTimeline.seek(0.5);
      },
      async togglePlay(e: Event) {
        e.preventDefault();
        e.stopPropagation();
        if (videoPlayer) {
          if (videoPlayer.paused()) {
            await videoPlayer.play();
          } else {
            videoPlayer.pause();
          }
        }
      },
      forward() {
        if (videoPlayer) {
          videoPlayer.currentTime(videoPlayer.currentTime() + 10);
        }
      },
      backward() {
        if (videoPlayer) {
          videoPlayer.currentTime(videoPlayer.currentTime() - 10);
        }
      },
      onOverlayClick() {
        if (videoPlayer) {
          if (videoPlayer.paused()) {
            videoPlayer.play();
          } else {
            videoPlayer.pause();
          }
        }
      },
    };
  },
});
</script>
<style lang="sass" scoped>
.video-player
  position: relative
  background-color: black

.player-overlay
  position: absolute
  background-color: rgba(0,0,0,0.3)
  left: 0
  top: 0
  .upper
    .title
      font-size: 24px
      font-weight: medium
    .author-info
      .author-name
        font-size: 12px
        font-weight: medium
      .author-followers
        font-size: 12px
.video-js
  width: 100%
  height: 100%
.audio-player
  display: hidden
</style>
